package cn.flying.cloud.base.common.utils.lang;

import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.springframework.util.CollectionUtils;

/**
 * List和Tree树形结构的转换
 *
 * @author: admin
 * @date: 2023年07月05日 18:58
 * @version: 1.0
 */
public class TreeUtil {

    /**
     * List转Tree树形结构
     *
     * @param list
     * @param idFn
     * @param pidFn
     * @param setChild
     * @param rootCondition
     * @param <M>
     * @param <T>
     * @return
     */
    public static <M, T> List<M> listToTree(List<M> list,
                                            Function<M, T> idFn,
                                            Function<M, T> pidFn,
                                            BiConsumer<M, List<M>> setChild,
                                            Predicate<M> rootCondition) {
        Map<T, List<M>> listMap = list.stream().collect(Collectors.groupingBy(pidFn));
        list.stream().forEach(m -> setChild.accept(m, listMap.get(idFn.apply(m))));
        return list.stream().filter(rootCondition).collect(Collectors.toList());
    }

    /**
     * Tree树形结构转List
     *
     * @param source
     * @param target
     * @param getChildListFn
     * @param setChild
     * @param <M>
     * @return
     */
    public static <M> List<M> treeToList(List<M> source, List<M> target, Function<M, List<M>> getChildListFn, Consumer<M> setChild) {
        if (CollectionUtils.isEmpty(source)) {
            return target;
        }
        source.forEach(node -> {
            target.add(node);
            List<M> childList = getChildListFn.apply(node);
            if (!CollectionUtils.isEmpty(childList)) {
                treeToList(childList, target, getChildListFn, setChild);
            }
            setChild.accept(node);
        });
        return target;
    }
}
